/*
   生命周期本质上 是一个泛型的参数，他用来标注引用（&）参数的 有效作用域范围
   
   他不改变任何一个引用的实际存活时间，他只是描述多个应用之间存活时间的相对关系， 通过标注每个参数的有效存活范围来辅助编译器的 借用检测（Borrwo Checking）

   避免所用的引用不会比他们所引用的数据活得更久（垂悬引用（空指针））

   比较两个字符串 返回较长的那个，返回的 参数可能是 x 也可能是y 
   编译器无法确定返回参数的生命周期

fn longest(x: &str, y: &str) -> &str { 
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
 

 编译器提示 error[E0106]: missing lifetime specifier  
 存在不明确的生命周期
 应该 给函数内的 用到的 函数加上生命周期


*/

/*   
pub fn longest(x: &str, y: &str) -> &str { 
    if x.len() > y.len() {
        x
    } else {
        y
    }


}
*/

//自动推断
pub fn longests(x:&str) ->&str{
    x
}

pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str
 { 
    if x.len() > y.len() {
        x
    } else {
        y
    }

}

/* 
结构体中的生命周期 

当结构体的字段是一个引用时，我们必须为这个引用添加生命周期注解。这表示结构体实例不能比它所有字段中的引用存活得更久。


struct ImportantExcerpt<'a> {
    part: &'a str,
}
*/

/* 
编译时会提示不明确的生命周期 
当结构体的字段是一个 引用时， 我们必须为 这个引用添加生命周期的注解，表示 这个结构体实例不能比他内部字段的 引用活得更久（避免了空引用的发生）
struct ImportantExcerpt{
    part: &str,
}
*/

struct ImportantExcerpt<'a> {
    part: &'a str,
}

pub fn test(){
     let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt {
        part: first_sentence,
    };
    println!("{0}",i.part)
}


/*


生命周期省略规则

1.每一个是引用的参数都有它自己独立的生命周期。

fn foo(x: &i32) -> fn foo<'a>(x: &'a i32)

fn foo(x: &i32, y: &i32) -> fn foo<'a, 'b>(x: &'a i32, y: &'b i32)

2.如果只有一个输入生命周期参数，那么它被赋予所有输出生命周期参数。

fn foo<'a>(x: &'a i32) -> &'a i32

3.如果方法有多个输入生命周期参数，但其中一个是 &self 或 &mut self（是方法），那么所有输出生命周期参数被赋予 self 的生命周期。

这条规则使得方法的使用变得非常简洁，大多数情况下不需要注解。






*/

/*
  无界生命周期
 不安全代码(unsafe)经常会凭空产生引用或生命周期，这些生命周期被称为是 无界(unbound) 的。

无界生命周期往往是在解引用一个裸指针(裸指针 raw pointer)时产生的，换句话说，它是凭空产生的，因为输入参数根本就没有这个生命周期：

若一个输出生命周期被消除了，那么必定因为有一个输入生命周期与之对应。



fn f<'a, T>(x: *const T) -> &'a T {
    unsafe {
        &*x
    }
}
*/

/*
生命周期约束 HRTB 
生命周期约束跟特征约束类似，都是通过形如 'a: 'b 的语法，来说明两个生命周期的长短关系。  'a 比 'b 的生命周期长


struct DoubleRef<'a,'b:'a, T> {
    r: &'a T,
    s: &'b T
}

例如上述代码定义一个结构体，它拥有两个引用字段，类型都是泛型 T，每个引用都拥有自己的生命周期，
由于我们使用了生命周期约束 'b: 'a，因此 'b 必须活得比 'a 久，
也就是结构体中的 s 字段引用的值必须要比 r 字段引用的值活得要久。

*/
/*引用的生命周期正常来说应该从借用开始一直持续到作用域结束 */


/*NLL (Non-Lexical Lifetime)  引用的生命周期从借用处开始，一直持续到最后一次使用的地方。*/